---
title: 在enrichplot中使用更好的Label
author: gao
date: '2018-11-26'
slug: enrichplot-fancy-label
categories:
  - ggplot2
tags:
  - enrichplot
---

<script src="/rmarkdown-libs/header-attrs/header-attrs.js"></script>


<div id="go-term-太长-enrichplot-好局促怎么办" class="section level1">
<h1>GO term 太长, enrichplot 好局促怎么办?</h1>
<p>例如下面这个样子:</p>
<pre class="r"><code># 可重复运行的代码拿去
library(clusterProfiler)
library(org.Hs.eg.db)
library(ggplot2)

data(geneList, package = &quot;DOSE&quot;)
gene &lt;- names(geneList)[abs(geneList)&gt;3]
gene.df &lt;- bitr(gene, fromType = &quot;ENTREZID&quot;,
        toType = c(&quot;ENSEMBL&quot;, &quot;SYMBOL&quot;),
        OrgDb = org.Hs.eg.db)

ego &lt;- enrichGO(gene          = gene,
                universe      = names(geneList),
                OrgDb         = org.Hs.eg.db,
                ont           = &quot;BP&quot;,
                pAdjustMethod = &quot;BH&quot;,
                pvalueCutoff  = 0.01,
                qvalueCutoff  = 0.05,
                readable      = TRUE)</code></pre>
<p>这个例子中, 有一个 “microtubule cytoskeleton …” 特别长, 事实上有些 GO term 比这还要长很多. 不巧在这个例子中没有出现, 那就拿它开刀吧.</p>
<pre class="r"><code>dotplot(ego)</code></pre>
<p><img src="/post/2018-11-26-enrichplot-fancy-label_files/figure-html/unnamed-chunk-2-1.png" width="672" /></p>
<p>刀法比较犀利, 主要是定义一个短 label 的函数, 将其传递给 <code>scale_y_discrete()</code> 即可. <strong>在输出ggplot 对象时做修改</strong>.</p>
<pre class="r"><code>#&#39; Truncate string vector of ggplot axis label
#&#39;
#&#39; @param label    a ordered string vector
#&#39; @param maxLen   max length of character (nchar) to show in label
#&#39; @param maxWord  max count of words allowed to show in label
#&#39; @param pattern  Word separater
#&#39; @param dot      If true, three dots will added to truncated label
#&#39;
#&#39; @return a vector of truncated strings
#&#39; @export
#&#39;
#&#39; @examples
short_label &lt;- function(label, maxLen = 50, maxWord = 5, pattern = &quot; &quot;, dot = TRUE){
  l &lt;- strsplit(label, pattern)
  short_label &lt;- vector(&quot;character&quot;,length(l))
  
  for (i in seq_along(l)){
    truncated &lt;- FALSE
    s &lt;- l[[i]]
    if (length(s) &gt; maxWord){
      ll &lt;- paste(s[1:maxWord], collapse = &quot; &quot;)
      truncated &lt;- TRUE
    }
    else{
      ll &lt;- paste(s, collapse = &quot; &quot;)
    }
    
    if (nchar(ll) &gt; maxLen){
      ll &lt;- substr(ll, 1, maxLen)
      truncated &lt;- TRUE
    }
    
    if (dot &amp; truncated) ll &lt;- paste(ll, &quot;...&quot;,sep = &quot; &quot;)
    
    short_label[[i]] &lt;- ll
  }
  attr(short_label, &quot;pos&quot;) &lt;- attr(label,&quot;pos&quot;)
  return(short_label)
}</code></pre>
<p>默认最多显示 50 个字符, 5 个单词.</p>
<pre class="r"><code>dotplot(ego) + scale_y_discrete(label=short_label)</code></pre>
<p><img src="/post/2018-11-26-enrichplot-fancy-label_files/figure-html/unnamed-chunk-4-1.png" width="672" /></p>
<p>如果最多只显示 3 个单词, 则可以写成这样:</p>
<pre class="r"><code>dotplot(ego) + 
  scale_y_discrete(
    label=function(x)short_label(x,maxWord = 3)
    )</code></pre>
<p><img src="/post/2018-11-26-enrichplot-fancy-label_files/figure-html/unnamed-chunk-5-1.png" width="672" /></p>
<p><strong>注意</strong>: <code>short_label()</code> 带参数和不带参数时具有不同的调用方法.</p>
</div>
<div id="不满意-enrichplot-x轴排序怎么破" class="section level1">
<h1>不满意 enrichplot x轴排序怎么破?</h1>
<p>我觉得 compareCluster 的输出可能会更加有比较价值. 但是发现 x 轴的排序有时候会有一些问题.</p>
<p><code>compareCluster</code> 只能根据其本来固有的顺序排序, 这在程序上没有问题. 但用起来可能情况比较复杂.</p>
<pre class="r"><code>data(&quot;gcSample&quot;)

names(gcSample)</code></pre>
<pre><code>## [1] &quot;X1&quot; &quot;X2&quot; &quot;X3&quot; &quot;X4&quot; &quot;X5&quot; &quot;X6&quot; &quot;X7&quot; &quot;X8&quot;</code></pre>
<pre class="r"><code>set.seed(0)
names(gcSample) &lt;- sample(seq(0,28,by=4),8)
names(gcSample)</code></pre>
<pre><code>## [1] &quot;20&quot; &quot;0&quot;  &quot;12&quot; &quot;24&quot; &quot;4&quot;  &quot;16&quot; &quot;8&quot;  &quot;28&quot;</code></pre>
<pre class="r"><code>ck &lt;- compareCluster(geneClusters = gcSample, fun = &quot;enrichKEGG&quot;)</code></pre>
<p>比如下面的例子中, 我们是想让 x 轴依数字大小(Time)排序的. 但是由于这个顺序与 <code>list</code> 顺序不同, 导致结果差强人意.</p>
<pre class="r"><code>dotplot(ck)</code></pre>
<p><img src="/post/2018-11-26-enrichplot-fancy-label_files/figure-html/unnamed-chunk-7-1.png" width="960" /></p>
<p>这只是一个 <code>list</code> 输入的例子, 可以通过改 name 变更顺序(就行我刚刚做的那样). 但是, 如果数据是放在 <code>data.frame</code> 中的, 存在多个分组条件, 每个条件按因子的 <code>level</code> 排好序.
那么由于 <code>compareCluster</code> 和 <code>dotplot</code> 操作时会将其转变成 <code>character</code>, 顺序会丢失, 导致最终结果是按照字母顺序输出的.</p>
<p>这种情况下, 你去改原始数据都是没有用的(需要给程序打补丁).</p>
<p>为了解决这个问题, 强行在 <strong>在已经输出的ggplot 对象上修改</strong>.</p>
<p>由于 <code>ggplot</code> 隐式输出的是一个对象, 其数据可以访问和修改. 出来的图, 先改一下再保存不就可以了吗?</p>
<pre class="r"><code>p &lt;- dotplot(ck)

levels(p$data$Cluster)</code></pre>
<pre><code>## [1] &quot;0\n(383)&quot;  &quot;12\n(187)&quot; &quot;24\n(405)&quot; &quot;4\n(445)&quot;  &quot;16\n(264)&quot; &quot;8\n(317)&quot; 
## [7] &quot;28\n(160)&quot;</code></pre>
<pre class="r"><code>p$data$Cluster &lt;- factor(p$data$Cluster, 
                         levels = c(&quot;0\n(245)&quot;, &quot;4\n(359)&quot;,  &quot;8\n(172)&quot;, &quot;12\n(412)&quot;, &quot;16\n(157)&quot;, &quot;20\n(388)&quot;,    &quot;24\n(301)&quot;),
                         labels = c(0,4,8,12,16,20,24))

p + xlab(&quot;Time (h)&quot;) + scale_y_discrete(label=short_label)</code></pre>
<p><img src="/post/2018-11-26-enrichplot-fancy-label_files/figure-html/unnamed-chunk-8-1.png" width="672" /></p>
<p>这两种“骚操作”, 分别相当于基因表达时“转录后修饰”和“翻译后修饰”. 嗯, 是有这么个意思. 都是在 “biobabble” 公众号学到的, 结合具体问题分享一下. 共同进步吧!</p>
</div>
